<template>
  <div class="wrap">
    <div class="search-wrap"></div>
    <div class="table-header">
      <div>数据库管理(playdatabase)</div>
      <div>
        <el-button class="add" type="primary" size="default" @click="tableErd"
          >ERD图</el-button
        >
        <el-button class="add" type="primary" size="default" @click="addTable"
          >新增</el-button
        >
      </div>
    </div>
    <el-table :data="tableList" style="width: 100%">
      <!-- <el-table-column prop="id" label="id"> </el-table-column> -->
      <el-table-column prop="tableName" label="表名"> </el-table-column>
      <el-table-column prop="tableComment" label="描述"> </el-table-column>
      <el-table-column prop="createTime" label="创建时间"> </el-table-column>
      <el-table-column prop="engine" label="引擎"> </el-table-column>
      <el-table-column fixed="right" label="操作" width="320">
        <template v-slot="scope">
          <el-button
            size="small"
            type="primary"
            @click.stop="editorTable(scope.row)"
          >
            编辑
          </el-button>
          <el-button
            size="small"
            type="warning"
            @click.stop="codeGeneration(scope.row)"
          >
            代码生成
          </el-button>
          <el-popconfirm
            title="确认要删除该列?"
            confirm-button-text="是"
            cancel-button-text="否"
            @confirm="deleteTable(scope.row)"
          >
            <template #reference>
              <el-button> 删除 </el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <!-- 表结构 -->
    <el-dialog
      v-model="dialogTableVisible"
      :close-on-click-modal="false"
      title="表结构"
      width="70%"
    >
      <el-form
        :model="form"
        ref="ruleForm"
        :rules="formRules"
        label-position="top"
      >
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="表名" prop="tableName" label-width="140px">
              <el-input
                v-model.trim="form.tableName"
                :disabled="tableDialogType == 'editor'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="描述" prop="tableComment" label-width="140px">
              <el-input
                v-model.trim="form.tableComment"
                :disabled="tableDialogType == 'editor'"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>

      <div>
        <el-button class="add" type="primary" size="default" @click="addFeield"
          >新增字段</el-button
        >
      </div>

      <el-table :data="fieldList" style="width: 100%">
        <!-- <el-table-column prop="id" label="id"> </el-table-column> -->
        <el-table-column prop="field" label="字段名称" width="150">
        </el-table-column>
        <el-table-column prop="comment" label="描述"> </el-table-column>
        <el-table-column prop="type" label="字段类型" width="150">
        </el-table-column>
        <el-table-column prop="null" label="是否可空"> </el-table-column>
        <el-table-column prop="default" label="默认值"> </el-table-column>
        <el-table-column fixed="right" label="操作" width="200">
          <template v-slot="scope">
            <template
              v-if="
                !['uid', 'create_time', 'update_time'].includes(scope.row.field)
              "
            >
              <el-button
                size="small"
                type="primary"
                @click.stop="editorFeield(scope.row)"
              >
                编辑
              </el-button>
              <el-popconfirm
                title="确认要删除该字段?"
                confirm-button-text="是"
                cancel-button-text="否"
                @confirm="deleteField(scope.row)"
              >
                <template #reference>
                  <el-button> 删除 </el-button>
                </template>
              </el-popconfirm>
            </template>

            <template v-else> 系统默认字段 </template>
          </template>
        </el-table-column>
      </el-table>

      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogTableVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmTable"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 字段属性 -->
    <el-dialog
      v-model="dialogFieldVisible"
      :close-on-click-modal="false"
      title="字段属性"
      width="45%"
    >
      <el-form
        :model="formField"
        ref="ruleFormField"
        :rules="formFieldRules"
        label-position="left"
      >
        <el-form-item label="字段名称" label-width="80px" prop="field">
          <el-input v-model.trim="formField.field" :disabled="false" />
        </el-form-item>
        <el-form-item label="字段类型" label-width="80px" prop="type">
          <!-- <el-input v-model="formField.type" :disabled="false" /> -->
          <el-select v-model="formField.type" placeholder="请选择">
            <el-option label="bigint" value="bigint"></el-option>
            <el-option label="varchar" value="varchar(255)"></el-option>
            <el-option label="date" value="date"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="是否可空" label-width="80px" prop="null">
          <!-- <el-input v-model="formField.null" :disabled="false" /> -->
          <el-select v-model="formField.null" placeholder="请选择">
            <el-option label="YES" value="YES"></el-option>
            <el-option label="NO" value="NO"></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="默认值" label-width="80px">
          <el-input v-model.trim="formField.default" :disabled="false" />
        </el-form-item>
        <el-form-item label="备注" label-width="80px" prop="comment">
          <el-input v-model.trim="formField.comment" :disabled="false" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogFieldVisible = false">取消</el-button>
          <el-button type="primary" @click="confirmField"> 确定 </el-button>
        </span>
      </template>
    </el-dialog>

    <!--  ERD图-->
    <!-- ERD -->
    <el-dialog
      v-model="dialogErdVisible"
      :close-on-click-modal="false"
      title="ERD图"
      :fullscreen="true"
    >
      <div
        id="myDiagramDiv"
        v-if="dialogErdVisible"
        style="width: 100%; height: 750px; background-color: #dae4e0"
      ></div>
    </el-dialog>
  </div>
</template>
    
    <script>
import request from "utils/request";
import { ElMessage, ElMessageBox } from "element-plus";
import { initErd } from "./init-erd";

/**
 * 从response读取流下载
 * @param response 响应体
 * @param suffix 文件后缀名
 */
function downloadBlob(response, suffix) {
  let fileName = "xxxx.ts";
  let blob = new Blob([response]); //response.data为后端传的流文件
  let url = window.URL.createObjectURL(blob);
  let downloadElement = document.createElement("a");
  downloadElement.style.display = "none";
  downloadElement.href = url;
  downloadElement.download = fileName;
  document.body.appendChild(downloadElement);
  downloadElement.click();
  document.body.removeChild(downloadElement);
  window.URL.revokeObjectURL(url);
}

// 自定义排序函数
function customSort(a, b) {
  let specialCategories = ["uid", "create_time", "update_time"];

  if (
    specialCategories.includes(a.field) ||
    specialCategories.includes(b.field)
  ) {
    if (
      specialCategories.indexOf(a.field) < specialCategories.indexOf(b.field)
    ) {
      return -1;
    } else {
      return 1;
    }
  }

  // 如果b是特殊类别而a不是，b应该排在前面（实际上这种情况不会发生，因为我们已经处理了所有特殊类别）
  if (specialCategories.includes(b.field)) {
    return -1; // b排在后面（但实际上不会执行到这里）
  }
  // 如果a是特殊类别而b不是，a应该排在前面
  if (specialCategories.includes(a.field)) {
    return 1; // a排在前面
  }
}

export default {
  name: "NestAdminDraw",

  data() {
    return {
      dialogTableVisible: false,
      dialogFieldVisible: false,
      dialogErdVisible: false,
      dialogDrawTripType: 1, //1 新增 0 编辑
      search: {
        title: "",
      },
      tableDialogType: "", //add editor
      fieldDialogType: "", //add editor
      form: {
        tableName: "",
        tableComment: "",
      },
      formField: {
        field: "",
        type: "",
        null: "",
        default: "",
        comment: "",
      },
      tableList: [],
      fieldList: [],
      currentEditorField: {},
      formRules: {
        tableName: [
          { required: true, message: "请输入表名", trigger: "blur" },
          {
            pattern: /^[a-z][a-z0-9_]*$/,
            message: "请输入小写字母、下划线、数字，不能以数字和下划线开头",
            trigger: "blur",
          },
        ],
        tableComment: [
          { required: true, message: "请输入表注释", trigger: "blur" },
        ],
      },
      formFieldRules: {
        field: [
          { required: true, message: "请输入字段名", trigger: "blur" },
          {
            pattern: /^[a-z][a-z0-9_]*$/,
            message: "请输入小写字母、下划线、数字，不能以数字和下划线开头",
            trigger: "blur",
          },
        ],
        type: [
          { required: true, message: "请选择字段类型", trigger: "change" },
        ],
        null: [
          { required: true, message: "请选择是否可为空", trigger: "change" },
        ],
        comment: [
          { required: true, message: "请填写字段注释", trigger: "change" },
        ],
      },
    };
  },

  async mounted() {
    await this.getTableList();
  },
  watch: {
    dialogTableVisible: {
      handler(value) {
        if (!value) {
          Object.assign(this.form, {
            tableName: "",
            tableComment: "",
          });
          this.$refs["ruleForm"].resetFields();
        }
      },
    },
    dialogFieldVisible: {
      handler(value) {
        if (!value) {
          Object.assign(this.formField, {
            field: "",
            type: "",
            null: "",
            default: "",
            comment: "",
          });
          this.$refs["ruleFormField"].resetFields();
        }
      },
    },
  },
  computed: {
    userId() {
      return this.$store.state.user.userInfo.id;
    },
  },
  methods: {
    addFeield() {
      this.fieldDialogType = "add";
      let defaultName =  "field_"+ (new Date().getTime().toString()).slice(-4);
      this.formField = {
        field: defaultName,
        type: "varchar(255)",
        null: "YES",
        default: "",
        comment: defaultName,
      };
      this.currentEditorField = {};
      this.dialogFieldVisible = true;
    },
    editorFeield(row) {
      this.fieldDialogType = "editor";
      this.dialogFieldVisible = true;
      let field = this.fieldList.find((item) => {
        if (item.field == row.field) {
          return true;
        }
      });
      console.log(field);
      try {
        this.formField = JSON.parse(JSON.stringify(field)) || field || {};
        this.currentEditorField =
          JSON.parse(JSON.stringify(field)) || field || {};
      } catch (error) {
        this.formField = {
          field: "",
          type: "",
          null: "",
          default: "",
          comment: "",
        };
      }
    },
    async getTableList() {
      let ret = await request.get("/database/get-table-list");
      if (ret.code == 200) {
        this.tableList = ret.data || [];
      }
    },
    addTable() {
      let defaultName = "table_"+ (new Date().getTime().toString()).slice(-4);
      this.tableDialogType = "add";
      this.form.tableName = defaultName;
      this.form.tableComment = defaultName;
      this.fieldList = [];
      this.dialogTableVisible = true;
    },
    async editorTable(row) {
      //  ElMessage.warning("暂不支持编辑");
      this.tableDialogType = "editor";
      this.form.tableName = row.tableName;
      this.form.tableComment = row.tableComment;
      let ret = await request.get("/database/get-table-structure", {
        tableName: row.tableName,
        tableComment: row.tableComment,
      });
      if (ret.code == 200) {
        this.dialogTableVisible = true;
        this.fieldList = ret.data.map((item) => item).sort(customSort) || [];
        console.log(ret.data);
      }
    },
    async confirmTable() {
      if (this.tableDialogType == "editor") {
        this.dialogTableVisible = false;
        return false;
      }

      if (this.fieldList.length == 0) {
        ElMessage.warning("请添加字段");
        return false;
      }

      this.$refs["ruleForm"].validate(async (valid) => {
        if (valid) {
          let ret = await request.post("/database/create-table", {
            name: this.form.tableName,
            comment: this.form.tableComment,
            columns: this.fieldList,
          });
          if (ret.code == 200) {
            ElMessage.success("创建成功成功");
            this.dialogTableVisible = false;
            this.getTableList();
          }
        }
      });
    },
    async confirmField() {
      this.$refs["ruleFormField"].validate(async (valid) => {
        if (valid) {
          if (this.tableDialogType == "add") {
            try {
              this.fieldList.push(JSON.parse(JSON.stringify(this.formField)));
              this.dialogFieldVisible = false;
            } catch (error) {
              ElMessage.warning("字段插入失败");
            }
          } else {
            if (this.fieldDialogType == "editor") {
              let ret = await request.post("/database/update-table-field", {
                tableName: this.form.tableName,
                oldField: this.currentEditorField.field,
                newField: this.formField.field,
                type: this.formField.type,
                null: this.formField.null,
                default: this.formField.default,
                comment: this.formField.comment,
              });
              if (ret.code == 200) {
                ElMessage.success("编辑成功");
                this.dialogFieldVisible = false;
                this.editorTable({ tableName: this.form.tableName });
              }
            } else {
              let ret = await request.post("/database/add-table-field", {
                tableName: this.form.tableName,
                field: this.formField.field,
                type: this.formField.type,
                null: this.formField.null,
                default: this.formField.default,
                comment: this.formField.comment,
              });
              if (ret.code == 200) {
                ElMessage.success("新增成功");
                this.dialogFieldVisible = false;
                this.editorTable({ tableName: this.form.tableName });
              }
            }
          }
        }
      });
    },
    async deleteTable(row) {
      let ret = await request.post("/database/remove-table", {
        tableName: row.tableName,
      });
      if (ret.code == 200) {
        ElMessage.success("删除成功");
        this.getTableList();
      }
    },
    async deleteField(row) {
      let ret = await request.post("/database/remove-table-field", {
        tableName: this.form.tableName,
        field: row.field,
      });
      if (ret.code == 200) {
        ElMessage.success("删除成功");
        this.editorTable({ tableName: this.form.tableName });
      }
    },
    async codeGeneration(row) {
      // ElMessage.warning("暂不支持代码生成");

      let res = await request.download(
        "/database/generate-and-stream?tableName=" + row.tableName
      );
      // let blob = new Blob([res], { type: "application/zip" });
      let blob = new Blob([res]);
      // 设置下载的内容以及格式，zip文件必须设置type: "application/zip"
      const url = window.URL.createObjectURL(blob); // 设置路径
      const link = window.document.createElement("a"); // 创建a标签
      link.href = url;
      link.download = row.tableName + ".zip"; // 设置文件名
      link.style.display = "none";
      link.click();
      URL.revokeObjectURL(url); // 释放内存
    },
    async getTableAndFieldInfo() {
      let ret = await request.get("/database/get-table-and-field-info", {});
      if (ret.code == 200) {
        initErd(ret.data);
      }
    },
    tableErd() {
      this.dialogErdVisible = true;
      this.getTableAndFieldInfo();
    },
  },
};
</script>
    
    <style lang="scss" scoped>
.wrap {
  .headPictureCol {
    width: 32px;
    height: 32px;
    overflow: hidden;
    border-radius: 50%;
  }
  .search-wrap {
    display: flex;
    margin-bottom: 15px;
    .search-class {
      margin-left: 20px;
    }
  }
  .table-header {
    display: flex;
    line-height: 50px;
    padding: 0 10px;
    justify-content: space-between;
    align-items: center;
  }
}
</style>
    